package fr.gestproj.bean.securite;

import fr.gestproj.utils.UtilsJsf;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.faces.FacesException;
import javax.faces.application.NavigationHandler;
import javax.faces.application.ViewExpiredException;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;
import org.springframework.security.web.authentication.rememberme.CookieTheftException;

/**
 *
 * @author Parrot
 */
public class CustomExceptionHandler extends ExceptionHandlerWrapper {

    public final static String PACKAGE_APPLICATION = "fr.gestproj";

        private ExceptionHandler wrapped;

        public CustomExceptionHandler(ExceptionHandler exception) {
                this.wrapped = exception;
        }

        @Override
        public ExceptionHandler getWrapped() {
                return wrapped;
        }

        @Override
        public void handle() throws FacesException {

                final Iterator<ExceptionQueuedEvent> iterator = getUnhandledExceptionQueuedEvents().iterator();
                while (iterator.hasNext()) {
                        ExceptionQueuedEvent event = iterator.next();
                        ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
                        Throwable exception = context.getException();
                        final FacesContext facesContext = FacesContext.getCurrentInstance();
                        final NavigationHandler navigation = facesContext.getApplication().getNavigationHandler();
                        try {
                                String result = doNavigation(exception, facesContext);
                                navigation.handleNavigation(facesContext, null, result);
                                facesContext.renderResponse();
                        } finally {
                                iterator.remove();
                        }
                }
                getWrapped().handle();
        }

        private String doNavigation(Throwable exception, FacesContext facesContext) {
                if (exception instanceof ViewExpiredException || exception instanceof CookieTheftException) {
                        return "/accueil.xhtml";
                }
                // LOGGER
                initTechnicalError(exception, facesContext);
                UtilsJsf.ajoutMessageError("Une erreur technique est survenue. Si le problème persiste, merci de contacter le support technique.");
                return "/pages/public/errors/500.xhtml";
        }

        private void initTechnicalError(Throwable exception, FacesContext facesContext) {
                while (exception.getCause() != null) {
                        exception = exception.getCause();
                }
                final Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
                requestMap.put("exception.class", exception.getClass());
                requestMap.put("exception.message", exception.getMessage());
                List<String> listeTrace = new ArrayList();
                for (StackTraceElement trace : exception.getStackTrace()) {
                        if (trace.getClassName().startsWith(PACKAGE_APPLICATION)) {
                                listeTrace.add(trace.toString());
                        }
                }
                requestMap.put("exception.stacktrace", listeTrace);
        }

}
